package org.makcro.sms.services.chat.web.client.mvc;

import java.util.List;

import org.makcro.sms.services.chat.web.client.AppEvents;
import org.makcro.sms.services.chat.web.client.Constants;
import org.makcro.sms.services.chat.web.client.mvc.view.AnswerView;
import org.makcro.sms.services.chat.web.client.services.message.MessageServiceAsync;
import org.makcro.sms.services.chat.web.shared.dto.HistoryItemDto;
import org.makcro.sms.services.chat.web.shared.dto.QuestionDto;

import com.extjs.gxt.ui.client.Registry;
import com.extjs.gxt.ui.client.event.EventType;
import com.extjs.gxt.ui.client.mvc.AppEvent;
import com.extjs.gxt.ui.client.mvc.Controller;
import com.extjs.gxt.ui.client.mvc.Dispatcher;
import com.extjs.gxt.ui.client.widget.Info;
import com.google.gwt.user.client.rpc.AsyncCallback;

public class AnswerController extends Controller {

	private AnswerView			view;
	private MessageServiceAsync	messageServiceAsync;

	public AnswerController() {
		registerEventTypes( AppEvents.PREPARE_ANSWER );
		registerEventTypes( AppEvents.ANSWER_TEXT_CHANGED );
		registerEventTypes( AppEvents.QUESTION_RESERVATION_CANCELED );
		registerEventTypes( AppEvents.ANSWER_ABOUT_TO_BE_SENT );
	}

	@Override
	protected void initialize() {
		super.initialize();
		messageServiceAsync = Registry.get( Constants.Services.MessageService );
		view = new AnswerView( this );
	}

	@Override
	public void handleEvent(AppEvent event) {
		EventType type = event.getType();
		if (type == AppEvents.PREPARE_ANSWER) {
			onPrepareAnswer( event );
		}

		else if (type == AppEvents.ANSWER_TEXT_CHANGED) {
			onAnswerTextChanged( event );
		}
		else if (type == AppEvents.QUESTION_RESERVATION_CANCELED) {
			onCancelQuestionReservation( event );
		}
		else if (type == AppEvents.ANSWER_ABOUT_TO_BE_SENT) {
			forwardToView( view, event );
			onAnserAboutToBeSent( event );
		}
	}

	private void onAnserAboutToBeSent(AppEvent event) {
		QuestionDto questionDto = Registry.get( Constants.CURRENT_QUESITON );
		String messageText = event.<String> getData();

		messageServiceAsync.sendMessage( questionDto.getCoreID(), messageText, new AsyncCallback<Long>() {

			@Override
			public void onSuccess(Long result) {
				onMessageSent( result );
			}

			@Override
			public void onFailure(Throwable caught) {
				onMessageSendFailure( caught );
			}
		} );

	}

	protected void onMessageSendFailure(Throwable caught) {
		forwardToView( view, new AppEvent( AppEvents.ANSWER_SENDING_FAILED ) );
		throw new RuntimeException( caught );
	}

	protected void onMessageSent(Long result) {
		// check if message was successfully sent
		if (result > 0) {
			Info.display( "Obavestenje", "Poruka uspesno poslata" );
			AppEvent event = new AppEvent( AppEvents.ANSWER_SENT );
			forwardToView( view, event );
			Dispatcher.get().dispatch( event );

		}
		else {
			Info.display( "Upozorenje", "Slanje poruke nije uspelo. Kod greske " + result );
			onCancelQuestionReservation( null );
		}
	}

	private void onCancelQuestionReservation(AppEvent event) {

		QuestionDto questionDto = Registry.get( Constants.CURRENT_QUESITON );

		messageServiceAsync.cancelQuestionReservation( questionDto.getQuestionID(), new AsyncCallback<Void>() {

			@Override
			public void onSuccess(Void result) {
				Info.display( "Obavestenje", "Rezervacija poruke otkazana" );
			}

			@Override
			public void onFailure(Throwable caught) {

			}
		} );

	}

	private void onAnswerTextChanged(AppEvent event) {
		forwardToView( view, event );

	}

	private void onPrepareAnswer(final AppEvent event) {
		final QuestionDto questionDto = event.<QuestionDto> getData();
		// register current question and make it available globaly
		Registry.register( Constants.CURRENT_QUESITON, questionDto );
		// check if question is still available (not reserved by another agent)
		messageServiceAsync.checkAndReserveQuestion( questionDto.getQuestionID(), new AsyncCallback<Boolean>() {

			@Override
			public void onSuccess(Boolean result) {
				if (result) {
					onQuestionReservationSuccessful( questionDto );
				}
				else {
					Info.display( "Obavestenje", "Poruka je preuzeta od strane drugog operatera." );
				}
			}

			@Override
			public void onFailure(Throwable caught) {
				System.out.println( caught );
			}
		} );

	}

	protected void onQuestionReservationSuccessful(QuestionDto questionDto) {
		messageServiceAsync.getUserHistory( questionDto.getFromNumber(), new AsyncCallback<List<HistoryItemDto>>() {

			@Override
			public void onSuccess(List<HistoryItemDto> result) {
				// forward history list to view
				AppEvent event = new AppEvent( AppEvents.PREPARE_ANSWER, result );
				forwardToView( view, event );

			}

			@Override
			public void onFailure(Throwable caught) {
				System.out.println( caught );

			}
		} );

	}

}
